package com.czz.ucenter.service.impl;

import com.czz.common.exception.CustomerException;
import com.czz.common.exception.ResultCodeEnum;
import com.czz.ucenter.service.KaptchaService;
import com.czz.ucenter.vo.KaptchaVo;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName: KaptchaServiceImpl
 * @Author Czz
 * @Date 2020/3/31
 * @Time 18:32
 **/
@Service
public class KaptchaServiceImpl implements KaptchaService {

    @Autowired
    DefaultKaptcha kaptcha;

    @Autowired
    private StringRedisTemplate redisTemplate;

    static final String KAPTCHA_PREFIX = "verify:code:token:";

    @Override
    public KaptchaVo getVerifyCode() {
        try {
            KaptchaVo kaptchaVo = new KaptchaVo();
            // 生成文字验证码
            String text = kaptcha.createText();
            // 生成图片验证码
            ByteArrayOutputStream outputStream = null;
            BufferedImage image = kaptcha.createImage(text);
            outputStream = new ByteArrayOutputStream();
            ImageIO.write(image, "jpg", outputStream);

            //生成验证码对应token
            String codeToken = UUID.randomUUID().toString();

            //将验证码和验证码token存入redis，有效期五分钟
            this.redisTemplate.opsForValue().set(KAPTCHA_PREFIX + codeToken, text, 5, TimeUnit.MINUTES);

            //返回验证码base64
            kaptchaVo.setCodeImg(Base64.getEncoder().encodeToString(outputStream.toByteArray()));
            kaptchaVo.setCodeToken(codeToken);

            return kaptchaVo;

        } catch (IOException e) {
            throw new CustomerException(ResultCodeEnum.IMG_CODE_ERROR);
        }
    }

    @Override
    public Integer checkVerifyCode(KaptchaVo kaptchaVo) {
        //根据验证码token判断redis中是否存在该验证码，如不存在则返回验证码过期
        String redisImg = this.redisTemplate.opsForValue().get(KAPTCHA_PREFIX + kaptchaVo.getCodeToken());
        if (StringUtils.isEmpty(redisImg)){
            return 1;
        }

        //存在验证码，但对比不一致，则返回验证码错误
        if (!kaptchaVo.getCodeImg().equals(redisImg)){
            return 2;
        }
        //对比一致，返回验证码成功
        else {
            return 0;
        }
    }

    @Override
    public KaptchaVo updateVerifyCode(KaptchaVo kaptchaVo) {
        //根据验证码token删除redis中信息
        this.redisTemplate.delete(KAPTCHA_PREFIX + kaptchaVo.getCodeToken());

        //生成新的验证码并返回
        return this.getVerifyCode();
    }
}
